/**
 @author 迷途小羔羊
 2015.11.20
 */
module GYLite
{
									
		
	export class GYDataGrid extends GYGrid
	{
		protected _rowsData:GridData[];
		protected _colsData:GridData[];
		protected _maxGridWidth:number;
		protected _maxGridHeight:number;
		protected _rowsDataUpdate:boolean;
		protected _colsDataUpdate:boolean;
		protected _oldRows:number;
		protected _oldCols:number;
		/**行列宽高可变的Grid组件，行列数量随组件宽高自适应，若行列宽高固定，建议使用GYGrid
		 * @param cols 初始化列数据 0初始化 非0 则需要外部提供s.rowsData的行数据
		 * @param rows 初始化行数据 0初始化 非0 则需要外部提供s.colsData的列数据
		 * @param getGridFunc():IItemRender 返回自定义格子对象的方法 
		 * @param setGridFunc(IItemRender, any) 设置格子数据的方法*/
		public constructor(cols:number, rows:number,getGridFunc:Function=null, getThisObject:any=null, setGridFunc:Function=null, setThisObject:any=null)
		{
			super(0, 0, getGridFunc, getThisObject, setGridFunc, setThisObject);
		}
		protected initComponent():void
		{var s = this;
			super.initComponent();			
			s._maxGridWidth = 0;
			s._maxGridHeight = 0;
			s._rowsDataUpdate = false;
			s._colsDataUpdate = false;
			s._oldRows=0;
			s._oldCols=0;

			if(s._rows == 0)
				s._rowsData = new Array<GridData>();
			if(s._cols == 0)
				s._colsData = new Array<GridData>();
			if(s._boxH == 0)s._boxH = GYDataGrid.default_boxH;
			if(s._boxW == 0)s._boxW = GYDataGrid.default_boxW;
		}
		/**@inheritDoc*/
		public scrollToPos(row:number,col:number):void
		{var s = this;
			var gridData:GridData;
			gridData = s.rowsData[row];
			s._vScroller.position = gridData.posY;
			gridData = s.colsData[col];
			s._hScroller.position = gridData.posX;
		}
		/**@inheritDoc*/
		public scrollToEndPos(row:number,col:number):void
		{var s = this;
			var gridData:GridData;
			gridData = s.rowsData[row];
			s._vScroller.position = gridData.posY - s._innerHeight + gridData.height;
			gridData = s.colsData[col];
			s._hScroller.position = gridData.posX - s._innerWidth + gridData.width;
		}
		/**每行的格子信息*/
		public get rowsData():GridData[]
		{var s = this;
			return s._rowsData;
		}
		/**每列格子信息*/
		public get colsData():GridData[]
		{var s = this;
			return s._colsData;
		}
		protected getRowGridData(val:number):GridData
		{var s = this;
			if(val < s._rowsData.length)
				return s._rowsData[val];
			var i:number,len:number;
			var gridData:GridData,oldGridData:GridData;
			len = val + 1;
			if(s._rowsData.length > 0)
				oldGridData = s._rowsData[s._rowsData.length - 1];
			for(i=s._rowsData.length;i<len;++i)
			{
				gridData = s._rowsData[i] = new GridData;
				gridData.index = i;
				gridData.height = s._boxH;
				if(s._boxH > s._maxGridHeight)
					s._maxGridHeight= s._boxH;
				if(oldGridData)
				{
					gridData.posY = oldGridData.posY + oldGridData.height;
				}
				oldGridData = gridData;
			}
			if(s.hasEventListener(GYGridEvent.ROWGRID_NUMCHANGE))
			{
				var e:GYGridEvent = new GYGridEvent(GYGridEvent.ROWGRID_NUMCHANGE);
				s.dispatchEvent(e);
			}
			return gridData;
		}
		protected getColGridData(val:number):GridData
		{var s = this;
			if(val < s._colsData.length)
				return s._colsData[val];
			var i:number,len:number;
			var gridData:GridData,oldGridData:GridData;
			len = val + 1;
			if(s._colsData.length > 0)
				oldGridData = s._colsData[s._colsData.length - 1];
			for(i=s._colsData.length;i<len;++i)
			{
				gridData = s._colsData[i] = new GridData;
				gridData.index = i;
				gridData.width = s._boxW;
				if(gridData.width > s._maxGridWidth)
					s._maxGridWidth= gridData.width;
				if(oldGridData)
				{
					gridData.posX = oldGridData.posX + oldGridData.width;
				}
				oldGridData = gridData;
			}
			if(s.hasEventListener(GYGridEvent.COLGRID_NUMCHANGE))
			{
				var e:GYGridEvent = new GYGridEvent(GYGridEvent.COLGRID_NUMCHANGE);
				s.dispatchEvent(e);
			}
			return gridData;
		}
		/**@inheritDoc*/
		public updateGrid():void
		{var s = this;
			var gridData:GridData;
			if(s._dataProvider && s._dataProvider.length > 0)
			{
				gridData = s.getRowGridData(s._dataProvider.length - 1);
				s._max=gridData.posY + gridData.height;
				if(s._dataProvider[0] && s._dataProvider[0].length > 0)
				{
					gridData = s.getColGridData(s._dataProvider[0].length - 1);
					s._horizonalMax=gridData.posX + gridData.width;
				}
			}
			else
			{
				s._max = 0;
				s._horizonalMax = 0;
			}
			s._vScroller.maximum = s._max-s._contentGrp.baseHeight;
			s._vScroller.barPercent = s._contentGrp.baseHeight/s._max;
			s.vScrollerPolicy = s._scrollerPolicy;
			if(s._vScroller.position > s._vScroller.maximum)
				s._vScroller.position = s._vScroller.maximum;
			s._hScroller.maximum = s._horizonalMax-s._contentGrp.baseWidth;
			s._hScroller.barPercent = s._contentGrp.baseWidth/s._horizonalMax;
			s.hScrollerPolicy = s._hScrollerPolicy;
			if(s._hScroller.position > s._hScroller.maximum)
				s._hScroller.position = s._hScroller.maximum;
			s.vScrollChange();
			s.hScrollChange();
		}
		/**@inheritDoc*/
		public get dataProvider():Array<any>
		{var s = this;
			return s._dataProvider;
		}
		public set dataProvider(val:Array<any>)
		{var s = this;
			if(!s._keepSelected)
			{
				s._selectedData = null;
				s._selectIndex = -1;
				if(s._canSelectNum > 1)
					s._selectList.length = 0;
			}
			s._dataProvider=(val?val:[]);			
					
			var grid:IItemRender;
			var endGridData:GridData;
			
			if(s._dataProvider.length > 0)
			{
				endGridData = s.getRowGridData(s._dataProvider.length - 1);
				s._max=endGridData.posY + endGridData.height;
			}
			else
				s._max=0;
			s._vScroller.maximum = s._max-s._contentGrp.baseHeight;
			s._vScroller.barPercent = s._contentGrp.baseHeight/s._max;
			s.vScrollerPolicy = s._scrollerPolicy;
			if(s._vScroller.position > s._vScroller.maximum)
				s._vScroller.position = s._vScroller.maximum;
			
			if(s._dataProvider[0] && s._dataProvider[0].length > 0)
			{
				endGridData = s.getColGridData(s._dataProvider[0].length - 1);
				s._horizonalMax=endGridData.posX + endGridData.width;
			}
			else
				s._horizonalMax = 0;
			s._hScroller.maximum = s._horizonalMax-s._contentGrp.baseWidth;
			s._hScroller.barPercent = s._contentGrp.baseWidth/s._horizonalMax;
			s.hScrollerPolicy = s._hScrollerPolicy;
			if(s._hScroller.position > s._hScroller.maximum)
				s._hScroller.position = s._hScroller.maximum;
			
			s.vScrollChange(null, true);
			s.hScrollChange(null, true);
		}
		protected vScrollChange(e:GYScrollerEvent=null, update:boolean = false,updatePos:boolean = true)
		{var s = this;
			if(s._dataProvider==null)
				return;
			var val:number;
			var w:number=0,h:number=0,offsetX:number=0,offsetY:number=0,i:number=0,j:number=0,len:number=0,len2:number=0;
			var nowLine:number=0,nowEndLine:number=0,iLine:number=0,jLine:number=0,posX:number=0,posY:number=0,maxSize:number=0,oldRows:number=0;
			var grid:IItemRender;
			var nowRowData:GridData, nowColData:GridData;
			var gridRows:Array<any>;
			var obj:any;
			var isShift:boolean;
			var n:number=0,nLen:number=0,m:number=0,mLen:number=0;

			maxSize = s._contentGrp.baseHeight;
			oldRows = s._rows;
			val = s._vScroller.position;
			nowRowData = s.getNowRow(val);
			nowColData = s.getNowCol(s._hScroller.position);
			if(nowRowData)
			{
				offsetY = val - nowRowData.posY;
				nowLine = nowRowData.index;
			}
			if(nowColData)
				offsetX = s._hScroller.position - nowColData.posX;
			posY = -offsetY;
			while(posY < maxSize)
			{
				iLine = nowLine+i;
				h = s.getRowGridData(iLine).height;
				posY += h;
				++i;
			}
			nowEndLine = nowLine + i - 1;
			s._rows = nowEndLine - nowLine + 1;
			if(nowLine > s._lastLine)
			{
				if(nowLine <= s._lastEndLine)
				{
					len = nowLine - s._lastLine;
					for(i=0;i<len;++i)
					{
						gridRows = s._grids[0];
						s._grids.splice(oldRows, 0,gridRows);
						s._grids.shift();
					}
				}
			}
			else
			{
				var tempInd:number=0;
				if(nowEndLine >= s._lastLine)
				{
					len = s._lastLine - nowLine;
					if(len > 0)
					{
						isShift = true;
						n = 0;
						nLen = s._lastEndLine - nowEndLine;
						if(nLen < 0)
						{
							m = s._lastEndLine - nowLine + 1;
							mLen =  m-nLen;
							nLen = len;
						}
						else
						{
							mLen = 0;
							nLen = len  - nLen;
						}
						for(i=0;i<len;++i)
						{
							tempInd = nowEndLine - s._lastLine + 1 + i;
							if(tempInd < s._grids.length)
							{
								gridRows = s._grids[tempInd];
								s._grids.splice(tempInd,1);
								s._grids.unshift(gridRows);
							}
							else
								s.unshiftRows();
						}
					}
				}
			}
			if(oldRows > s._rows)
			{
				for(i=s._rows;i < oldRows; ++i)
				{
					gridRows = s._grids[i];
					s.removeChildRows(gridRows);
				}
			}
			else
			{
				if(isShift)
				{
					for(i = n;i < nLen; ++i)
					{
						gridRows = s._grids[i];
						s.addChildRows(gridRows);
					}
					for(i = m;i < mLen; ++i)
					{
						if(i < s._grids.length)
						{
							gridRows = s._grids[i];
							s.addChildRows(gridRows);
						}
						else
							s.addRows();
					}
				}
				else
				{
					for(i=oldRows;i < s._rows; ++i)
					{
						if(i < s._grids.length)
						{
							gridRows = s._grids[i];
							s.addChildRows(gridRows);
						}
						else
							s.addRows();
					}
				}
			}
			
			posX = 0;
			posY = 0;
			for(i=0;i<s._rows;++i)
			{
				if(s._cols < 1)break;
				gridRows = s._grids[i];
				iLine = nowLine + i;
				nowRowData = s._rowsData[iLine];
				h = nowRowData.height;
				for(j=0;j<s._cols;++j)
				{
					grid = s._grids[i][j];
					jLine = s._lastLineH + j;
					if(iLine < s._dataProvider.length)
						obj = s._dataProvider[iLine][jLine];
					else
						obj = null;
					nowColData = s._colsData[jLine];
					w =	nowColData.width;
					if(updatePos)
					{
						grid.x = posX - offsetX;
						grid.y = posY - offsetY;
						s._contentGrp.checkOutSize(grid,false);
					}					
					if(s._lastLine > iLine || s._lastEndLine < iLine)
					{
						grid.row = iLine;
						grid.col = jLine;
						s.setGrid(grid,obj);
					}
					if(nowRowData.isSet)
						grid.height = h;
					else
						s.setGridHeight(iLine, grid.height);
					if(nowColData.isSet)
						grid.width = w;
					else
						s.setGridWidth(jLine, grid.width);
					posX += grid.width;
				}
				posX = 0;
				posY += grid.height;
			}
			
			s._lastLine = nowLine;
			s._lastEndLine = nowEndLine;
		}
		protected hScrollChange(e:GYScrollerEvent=null, update:boolean = false, updatePos:boolean = true):void
		{var s = this;
			if(s._dataProvider==null)
				return;
			var val:number=0;
			var w:number=0,h:number=0,offsetX:number=0,offsetY:number=0,i:number=0,j:number=0,len:number=0,len2:number=0;
			var iLine:number=0,jLine:number=0,posX:number=0,posY:number=0,maxSize:number=0,nowLine:number=0,nowEndLine:number=0,oldCols:number=0;
			var grid:IItemRender;
			var nowRowData:GridData, nowColData:GridData;
			var gridRows:Array<any>;
			var obj:any;
			var isShift:boolean;
			var n:number=0,nLen:number=0,m:number=0,mLen:number=0;
			
			maxSize = s._contentGrp.baseWidth;
			val = s._hScroller.position;
			nowRowData = s.getNowRow(s._vScroller.position);
			nowColData = s.getNowCol(val);
			if(nowRowData)
				offsetY = s._vScroller.position - nowRowData.posY;
			if(nowColData)
			{
				nowLine = nowColData.index;
				offsetX = val - nowColData.posX;
			}
			posX = -offsetX;
			while(posX < maxSize)
			{
				iLine = nowLine+i;
				w = s.getColGridData(iLine).width;
				posX += w;
				++i;
			}
			nowEndLine = nowLine + i - 1;
			oldCols = s._cols;
			s._cols = nowEndLine - nowLine + 1;
			if(nowLine > s._lastLineH)
			{
				if(nowLine <= s._lastEndLineH)
				{
					len2 = s._rows;
					len = nowLine - s._lastLineH;
					for(j=0;j<len2;++j)
					{
						gridRows = s._grids[j];
						for(i=0;i<len;++i)
						{
							grid = gridRows[0];
							gridRows.splice(oldCols, 0,grid);
							gridRows.shift();
						}
					}
				}
			}
			else
			{
				var tempInd:number=0;
				if(nowEndLine >= s._lastLineH)
				{
					len2 = s._rows;
					len = s._lastLineH - nowLine;
					if(len > 0)
					{
						isShift = true;
						n = 0;
						nLen = s._lastEndLineH - nowEndLine;
						if(nLen < 0)
						{
							m = s._lastEndLineH - nowLine + 1;
							mLen = m - nLen;
							nLen = len;
						}
						else
						{
							mLen = 0;
							nLen = len  - nLen;
						}
						for(j=0;j<len2;++j)
						{
							gridRows = s._grids[j];
							for(i=0;i<len;++i)
							{
								tempInd = nowEndLine - s._lastLineH + 1 + i;
								if(tempInd < gridRows.length)
								{
									grid = gridRows[tempInd];
									gridRows.splice(tempInd,1);
									gridRows.unshift(grid);
								}
								else
									gridRows.unshift(s.getGrid());
							}
						}
					}
				}
			}
			
			if(oldCols > s._cols)
			{
				len2 = s._rows;
				for(j=0;j<len2;++j)
				{
					gridRows = s._grids[j];
					for(i=s._cols;i < oldCols; ++i)
					{
						grid = gridRows[i];
						s._contentGrp.removeElement(grid);
					}
				}
			}
			else
			{
				if(isShift)
				{
					for(j=0;j<s._rows;++j)
					{
						gridRows = s._grids[j];
						for(i = n;i < nLen; ++i)
						{
							grid = gridRows[i];
							s._contentGrp.addElement(grid);
						}
						for(i = m;i < mLen; ++i)
						{
							if(i < gridRows.length)
							{
								grid = gridRows[i];
								s._contentGrp.addElement(grid);
							}
							else
								gridRows.push(s._contentGrp.addElement(s.getGrid()));
						}
					}
				}
				else
				{
					for(j=0;j<s._rows;++j)
					{
						gridRows = s._grids[j];
						for(i=oldCols;i < s._cols; ++i)
						{
							if(i < gridRows.length)
							{
								grid = gridRows[i];
								s._contentGrp.addElement(grid);							
							}
							else
								gridRows.push(s._contentGrp.addElement(s.getGrid()));
						}
					}
				}
				len2 = s._grids.length;
				for(j = s._rows;j<len2;++j)
				{
					gridRows = s._grids[j];
					for(i=oldCols;i < s._cols; ++i)
					{
						if(i >= gridRows.length)
							gridRows.push(s.getGrid());					
					}
				}
			}
			posX = 0;
			posY = 0;
			for(i=0;i<s._rows;++i)
			{
				if(s._cols < 1)break;
				gridRows = s._grids[i];
				iLine = s._lastLine + i;
				nowRowData = s._rowsData[iLine];
				h = nowRowData.height;
				for(j=0;j<s._cols;++j)
				{
					grid = s._grids[i][j];
					jLine = nowLine + j;
					if(iLine < s._dataProvider.length)
						obj = s._dataProvider[iLine][jLine];
					else
						obj = null;
					nowColData = s._colsData[jLine];
					w = nowColData.width;
					if(updatePos)
					{
						grid.x = posX - offsetX;
						grid.y = posY - offsetY;
					}					
					if(s._lastLineH > jLine || s._lastEndLineH < jLine || update)
					{
						grid.row = iLine;
						grid.col = jLine;
						s.setGrid(grid,obj);
					}
					if(nowRowData.isSet)
						grid.height = h;
					else
						s.setGridHeight(iLine, grid.height);
					if(nowColData.isSet)
						grid.width = w;
					else
						s.setGridWidth(jLine, grid.width);
					posX += grid.width;
				}
				posX = 0;
				posY += grid.height;
			}
			
			s._lastLineH = nowLine;
			s._lastEndLineH = nowEndLine;
		}
		protected unshiftRows():void
		{var s = this;
			var arr:Array<any>=[];
			var len:number = s._lastEndLineH - s._lastLineH + 1;
			while(--len>-1)
				arr[len] = s.getGrid();
			s._grids.unshift(arr);
		}
		protected addRows():void
		{var s = this;
			var arr:Array<any>=[];
			var len:number = s._lastEndLineH - s._lastLineH + 1;
			while(--len>-1)
				arr[len] = s._contentGrp.addElement(s.getGrid());
			s._grids.push(arr);
		}
		protected addChildRows(arr:Array<any>):void
		{var s = this;
			var i:number,len:number;
			len = s._lastEndLineH - s._lastLineH + 1;
			for(i=0;i<len;++i)
				s._contentGrp.addElement(arr[i]);
		}
		protected removeChildRows(arr:Array<any>):void
		{var s = this;
			var i:number,len:number;
			len = s._lastEndLineH - s._lastLineH + 1;
			for(i=0;i<len;++i)
				s._contentGrp.removeElement(arr[i]);
		}
		/**设置某列宽度
		 * @param ind 列索引 val 宽度值
		 * */
		public setGridWidth(ind:number,val:number):void
		{var s = this;
			if(ind >= s._colsData.length)
				return;
			var gridData:GridData;
			gridData = s._colsData[ind];
			if(gridData.width == val)
				return;
			if(s._maxGridWidth < val)
				s._maxGridWidth = val;
			gridData.width = val;
			gridData.isSet = true;
			s.invalidColsData();
			s.invalidGrids();
		}
		/**设置某行高度
		 * @param ind 行索引 val 高度值
		 * */
		public setGridHeight(ind:number,val:number):void
		{var s = this;
			if(ind >= s._rowsData.length)
				return;
			var gridData:GridData;
			gridData = s._rowsData[ind];
			if(gridData.height == val)
				return;
			if(s._maxGridHeight < val)
				s._maxGridHeight = val;
			gridData.height = val;
			gridData.isSet = true;
			s.invalidRowsData();
			s.invalidGrids();
		}
		protected getNowRow(val:number):GridData
		{var s = this;
			var st:number = (val / s._maxGridHeight >> 0);
			var i:number,len:number;
			var gridData:GridData,oldGridData:GridData;
			len = s._rowsData.length;
			for(i=st;i<len;++i)
			{
				gridData = s._rowsData[i];
				if(gridData.posY > val)
				{
					if(oldGridData)
						return oldGridData;
					return gridData;
				}
				oldGridData= gridData;
			}
			return gridData;
		}
		protected getNowCol(val:number):GridData
		{var s = this;
			var st:number = (val / s._maxGridWidth >> 0);
			var i:number,len:number;
			var gridData:GridData,oldGridData:GridData;
			len = s._colsData.length;
			for(i=st;i<len;++i)
			{
				gridData = s._colsData[i];
				if(gridData.posX > val)
				{
					if(oldGridData)
						return oldGridData;
					return gridData;
				}
				oldGridData= gridData;
			}
			return gridData;
		}
		/**刷新网格行数据*/
		public invalidRowsData():void
		{var s = this;
			if(s._rowsDataUpdate)
				return;
			s._rowsDataUpdate = true;
			s.displayChg();
		}
		/**刷新网格列数据*/
		public invalidColsData():void
		{var s = this;
			if(s._colsDataUpdate)
				return;
			s._colsDataUpdate = true;
			s.displayChg();
		}
		protected updateColsData():void
		{var s = this;
			var i:number,len:number;
			var gridData:GridData,oldGridData:GridData;
			len = s._colsData.length;
			for(i=0;i<len;++i)
			{
				gridData = s._colsData[i];
				if(oldGridData)
					gridData.posX = oldGridData.posX + oldGridData.width;
				oldGridData = gridData;
			}
		}
		protected updateRowsData():void
		{var s = this;
			var i:number,len:number;
			var gridData:GridData,oldGridData:GridData;
			len = s._rowsData.length;
			for(i=0;i<len;++i)
			{
				gridData = s._rowsData[i];
				if(oldGridData)
					gridData.posY = oldGridData.posY + oldGridData.height;
				oldGridData = gridData;
			}
		}
		public updateView():void
		{var s = this;
			if(s._rowsDataUpdate)
			{
				s.updateRowsData();
				s._rowsDataUpdate = false;
				if(s.hasEventListener(GYGridEvent.ROWGRID_DATACHANGE))
				{
					var gridEvent:GYGridEvent = new GYGridEvent(GYGridEvent.ROWGRID_DATACHANGE);
					s.dispatchEvent(gridEvent);
				}
			}
			if(s._colsDataUpdate)
			{
				s.updateColsData();
				s._colsDataUpdate = false;
				if(s.hasEventListener(GYGridEvent.COLGRID_DATACHANGE))
				{
					gridEvent = new GYGridEvent(GYGridEvent.COLGRID_DATACHANGE);
					s.dispatchEvent(gridEvent);
				}
			}
			super.updateView();
		}
		public static default_boxH:number = 40;
		public static default_boxW:number = 40;
	}
}
